/**
 * 前端算法的常见整理
 * 排序算法：冒泡排序
 * */
 let arr = [1111,1,4,5,76,2,3,8,9,123,1231,11,31,90,121,111,122]
/********************************/
// 冒泡排序的方法，前一个跟后一个比较，遇见大的往后排
function sortMax (arr){
    const len = arr.length;
    for(let i=0;i<len;i++){
        for(let j=0;j<len-i;j++){
            if(arr[j]>arr[j+1]){
                let temp = arr[j+1];
                arr[j+1] = arr[j];
                arr[j] = temp;
            }
        }
    }
    return arr
}
// console.log(sortMax(arr))
/********************************/
// 快速排序
function changeSort(arr){
    const len = arr.length
    for(let i=0;i<len;i++){
        let k = i;  // 记录当前的位置

        // 每一次找打最小的值
        for(let j= i+1;j<len;j++){
            k = arr[j]<arr[k]? j: k;
        }
        // 位置改变
        if(k!=i){
            let temp = arr[i]
            arr[i] = arr[k];
            arr[k] = temp
        }
    }
    return arr
}

// console.log(changeSort(arr))

/********************************/
// apply 方法实现 能够编写用于不同对象的方法
Function.prototype.myAplly=function(obj){
    obj = obj || window;
    obj.fn = this; // 添加一个属性为调用apply的函数
    let result;
    if(arguments[1]){  // 如果存在第一个参数
        result = obj.fn(...arguments[1]);
    }else{
        result = obj.fn()
    }
    delete obj.fn // 删除这个属性
    return result;
}

// let person = {
//     funllName:function(){
//         return this.firstName +'---'+this.lastName
//     }
// }
// let _str = {
//     firstName:'ht',
//     lastName:'zk'
// }
// var str=person.funllName.myAplly(_str)

// console.log(str)
/********************************/

// 实现一个 compose 多个函数累加
/**
 * 首先分解一下思路 add1,add2,add3 都是要计算返回值的 add1 x+1
 * */ 
function add1(x){
    return x + 1
}
function add2(x){
    return x + 2
}
function add3(x){
    return x + 3
}
// var addSum = compose(add1,add2,add3)
// var addSum = compose()
// var addSum = compose(add1)
var addSum = compose(add1,add2)
// console.log(addSum(1)) // 1+1+2+3 = 7


// 思路跑偏闭包的理解有错误，应该首先取到的是前边的数，再去后边的数，参考柯里化
// function compose(num){
//     return function(arguments){
//         var sum
//         for(var i=0;i<arguments.length;i++){
//             return sum+=arguments[i](num)
//         }
//     }
// }

function compose(...fn){
    if(!fn.length){
        return function(v){  // 这个参数就是返回的后边传入的compose()(v)就是类似的这个值
            // console.log(v)
            return v
        }
    }
    if(fn.length===1){   // 只有一个值的时候直接调用compose 里边的第一个函数的就行了
        return fn[0]
    }
    return fn.reduce(function(pre,cur){   // 为了把fn的函数数组分开，从而计算累加实现
        // console.log(pre,'--------------',cur,'-----------')
        return function(...args){        // 这一步是通过闭包实现获取第二个参数
            // console.log(args,'===========')
            return pre(cur(...args))   // 累加计算数值的方法
        }
    })
    // 简写的方式
    // if(!fn.length) return (v)=> v;
    // if(fn.length===1) return fn[0]
    // return fn.reduce(
    //     (pre,cur)=>
    //     (...args)=>
    //     pre(cur(...args))
    // )
}

/********************************/

function myNew(fn,...args){
    // 创建可以空对象，并且把原型链指向传递函数
    let obj = Object.create(fn.prototype)
    // 把函数的this指向为新对象
    let res = fn.call(obj,...args)
    // 感觉返回值判断是返回函数
    if(res && (typeof res === "object" || typeof res === 'function')) {
        return res;
    }
    return obj;
}

function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.sayName = function(){
    console.log(this.name)
}

const person = myNew (Person,'ht',18)
// person.sayName()

/********************************/